<template>
  <el-select :size="size" :placeholder="placeholder" :value="valueModel" @clear="clearChecked"
             v-loading="loading" clearable>
    <el-option ref="first" style="display: none" :value="valueModel" :label="label"></el-option>

    <div style="max-height: 200px;min-height: 160px">
      <div v-if="searchbar" style="width: 260px;">
        <div style="margin: 4px 8px;" v-show="showSearchbar">
          <el-input placeholder="模糊搜索" size="small" v-model="filterText" prefix-icon="fa fa-search" clearable
                    style="width: 100%;"></el-input>
        </div>
        <div class="pull-right text-primary" style="margin-right: 8px;cursor: pointer"
             @click="()=>{showSearchbar = !showSearchbar}">
          <i class="fa fa-search"></i>
        </div>
      </div>
      <div class="sea-scroll-bar">
        <el-tree ref="tree" node-key="id" :data="list"
                 default-expand-all accordion
                 @node-click="nodeClick" :filter-node-method="filterNode">

      <span class="custom-tree-node" slot-scope="{node, data}">
        <span><i :class="data.icon"></i>{{ data.label }}</span>
      </span>
        </el-tree>
      </div>
    </div>
  </el-select>
</template>

<script>
/* eslint-disable */
import Bamboo from "@/lang/bamboo";
import Layers from "@/lang/layers";
import TreeNode from "@/lang/bamboo/tree-node";
import Asserts from "@/lang/core/asserts";

/**
 * 下拉单选树形选择器
 *
 * 关于下拉数据的处理，还有进一步优化的空间，目前在组织树形机构的时候，会直接改动原始数据，
 * 一些特殊场合下，可能不希望组件改动数据，暂不决定处理这一问题，可以通过 Bamboo 工具类手动处理。
 */
export default {
    name: 'SeaSelectTree'

    , props: {
        value: {type: [String, Number], default: undefined}

        // 组件大小
        , size: {type: String, default: 'medium'}
        // 树形数据
        , options: {type: Array, default: Layers.array}

        // 数据查询
        , provider: {type: Function, default: undefined}

        // 搜索栏
        , searchbar: {type: Boolean, default: false}
        // 文字提示
        , placeholder: {type: String, default: ''}
    }, model: {
        //需要定义哪一个props可以用v-model绑定属性
        prop: 'value',
        //声明一个事件，调用之后，就会改变父级容器的值
        event: 'handlerValueChange'
    }
    , data() {
        return {
            // 值模型，任何时候都不允许为空，避免VUE联动失效
            valueModel: undefined
            // 组件配置
            , input: undefined
            // 显示的文本
            , label: ''
            // 属性数据列表
            , list: undefined
            // 过滤数值
            , filterText: ''
            // 展示搜索栏
            , showSearchbar: false

            // 数据查询中
            , loading: false
        }
    }
    , watch: {
        /**
         * 当前数值
         */
        value: {
            handler: function (val) {
                if (this.valueModel !== val) {
                    this.valueModel = val;
                    this.match();
                }
            }
        }
        /**
         * 下拉选项
         */
        , options: {
            handler: function (val) {
                this.setOptions(val)
            }
        }
        /**
         * 数据过滤
         */
        , filterText(val) {
            this.$refs.tree.filter(val);
        }
    }
    , created() {
        if (this.provider === undefined) {
            this.list = this.options;
        } else {
            this.query();
        }
    }
    , methods: {

        /**
         * 数据查询
         */
        query() {
            this.loading = true;
            this.provider().then(list => {
                if (Array.isArray(list)) {
                    if (list.length > 0) {
                        Asserts.isProtoTypeOf(TreeNode, list[0], 'select-tree response data is not instance of TreeNode!')
                    }
                    this.list = list
                } else {
                    console.error('select-tree only accept array-type!');
                }
            }).finally(() => this.loading = false);
        },

        /**
         * 过滤数据
         */
        filterNode: function (value, data) {
            if (!value) {
                return true;
            } else {
                return data.label.indexOf(value) !== -1;
            }
        }
        /**
         * 值改变事件
         */
        , onChange: function (val) {
            this.valueModel = val;
            this.$emit('handlerValueChange', val);
            this.$emit('change', val);
        }
        /**
         * 设置新的值
         */
        , setOptions: function (val) {
            this.list = Bamboo.isTree(val) ? val : Bamboo.toTree(val);
            this.match();
        }
        /**
         * 匹配值
         */
        , match: function () {
            let val = this.valueModel;
            if (Layers.isEmpty(val) || Layers.isEmpty(this.list)) {
                this.label = '';
            } else {
                let node = Bamboo.getNodeById(this.list, val);
                this.label = node === undefined ? val : node.label;
            }
        }
        /**
         * 清除选中的节点
         */
        , clearChecked: function () {
            this.label = '';
            this.onChange('');
        }
        /**
         * 节点点击事件
         *
         * @param node
         */
        , nodeClick(node) {
            this.label = node.label;
            // 主动触发点击事件，关闭下拉面板
            this.$refs.first.$el.click();
            this.onChange(node.id);
        }
    }
}
</script>
